package com.zxx.otherchaos.utils;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;

import com.zxx.otherchaos.MyApplication;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;


/**
 * NetWorkUtil
 *
 * @author zxx
 */
public class NetWorkUtil {

    public static final int NETWORK_TYPE_INVALID = 0;    //没有网络
    public static final int NETWORK_TYPE_WIFI = 1;   //wifi网络
    public static final int NETWORK_TYPE_2G = 2;       //2G网络
    public static final int NETWORK_TYPE_3G = 3;    //3G和3G以上网络，或统称为快速网络
    public static final int NETWORK_TYPE_4G = 4;


    private NetWorkUtil() {
        throw new AssertionError();
    }

    /**
     * 是否连接网络
     */
    public static boolean isConnectNet(@NonNull Context context) {
        try {
            NetworkInfo info = getNetworkInfo(context);
            return info != null && info.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 是否有活动的网络连接
     */
    public static boolean isNetworkAvailable(Context context) {
        try {
            NetworkInfo networkInfo = getNetworkInfo(context);
            return networkInfo != null && networkInfo.isAvailable();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    public static boolean isNetworkAvailable() {
        return isNetworkAvailable(MyApplication.getContext());
    }

    /**
     * 2. 判断WIFI是否连接
     */
    public static boolean isWifiConnected(@NonNull Context context) {
        return isConnected(context, ConnectivityManager.TYPE_WIFI);
    }

    /**
     * 3. 判断移动网络是否连接
     */
    public static boolean isMobileConnected(@NonNull Context context) {
        return isConnected(context, ConnectivityManager.TYPE_MOBILE);
    }

    private static boolean isConnected(Context context, int type) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        //检测API是否小于21，因为API21之后getNetworkInfo(int networkType)方法被弃用
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            NetworkInfo networkInfo = manager.getNetworkInfo(type);
            return networkInfo != null && networkInfo.isConnected();

        } else {
            return isConnected(manager, type);
        }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private static boolean isConnected(@NonNull ConnectivityManager manager, int type) {
        Network[] networks = manager.getAllNetworks();
        NetworkInfo networkInfo;

        for (Network network : networks) {
            networkInfo = manager.getNetworkInfo(network);
            if (networkInfo != null && networkInfo.getType() == type && networkInfo.isConnected()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取接入点类型
     */
    public static String getNetworkType() {
        NetworkInfo activeNetInfo = getNetworkInfo(MyApplication.getContext());
        if (activeNetInfo != null) {
            return activeNetInfo.getExtraInfo(); // 接入点名称: 此名称可被用户任意更改 如: cmwap,
        } else {
            return null;
        }
    }

    /**
     * 获取网络状态，wifi,wap,2g,3g.
     */
    public static int getNetWorkType(Context context) {
        int netType = NETWORK_TYPE_INVALID;
        NetworkInfo networkInfo = getNetworkInfo(context);

        if (networkInfo != null && networkInfo.isConnected()) {
            //String type = networkInfo.getTypeName();
            int type = networkInfo.getType();

            if (type == ConnectivityManager.TYPE_WIFI) {
                netType = NETWORK_TYPE_WIFI;

            } else if (type == ConnectivityManager.TYPE_MOBILE) {
                //String proxyHost = android.net.Proxy.getDefaultHost();
                //int subType = networkInfo.getSubtype();

                netType = netWorkType(context, networkInfo);
            }
        }

        return netType;
    }

    private static NetworkInfo getNetworkInfo(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return manager.getActiveNetworkInfo();
    }

    private static int netWorkType(Context context, NetworkInfo info) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        int type = info.getSubtype();
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            type = telephonyManager.getNetworkType();
        }
        switch (type) {
            case TelephonyManager.NETWORK_TYPE_GPRS:    // ~ 100 kbps
            case TelephonyManager.NETWORK_TYPE_EDGE:    // ~ 50-100 kbps
            case TelephonyManager.NETWORK_TYPE_CDMA:    // ~ 14-64 kbps
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:    // ~25 kbps
                return NETWORK_TYPE_2G;
            case TelephonyManager.NETWORK_TYPE_UMTS:    // ~ 400-7000 kbps
            case TelephonyManager.NETWORK_TYPE_EVDO_0:  // ~ 400-1000 kbps
            case TelephonyManager.NETWORK_TYPE_EVDO_A:  // ~ 600-1400 kbps
            case TelephonyManager.NETWORK_TYPE_EVDO_B:  // ~ 5 Mbps
            case TelephonyManager.NETWORK_TYPE_HSPA:    // ~ 700-1700 kbps
            case TelephonyManager.NETWORK_TYPE_HSDPA:   // ~ 2-14 Mbps
            case TelephonyManager.NETWORK_TYPE_HSUPA:   // ~ 1-23 Mbps
            case TelephonyManager.NETWORK_TYPE_EHRPD:   // ~ 1-2 Mbps
            case TelephonyManager.NETWORK_TYPE_HSPAP:   // ~ 10-20 Mbps:
                return NETWORK_TYPE_3G;
            case TelephonyManager.NETWORK_TYPE_IWLAN:
            case TelephonyManager.NETWORK_TYPE_LTE:     // ~ 10+ Mbps
                return NETWORK_TYPE_4G;
            //case TelephonyManager.NETWORK_TYPE_NR:
            //    return NETWORK_TYPE_5G;
            case TelephonyManager.NETWORK_TYPE_UNKNOWN:
            default:
                return NETWORK_TYPE_INVALID;
        }
    }


    /**
     * apk通知界面
     * Settings.ACTION_APP_NOTIFICATION_SETTINGS;  //应用通知界面
     */
    public static void openAppNotification(Context context) {
        try {
            Intent intent = new Intent();
            //打开是否通知界面
            intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
            String pkg = context.getApplicationInfo().packageName;
            int uid = context.getApplicationInfo().uid;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                //这种方案适用于 API 26, 即8.0（含8.0）以上可以用
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, pkg);
                intent.putExtra(Settings.EXTRA_CHANNEL_ID, uid);

            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //这种方案适用于 API21——25，即 5.0——7.1 之间的版本可以使用
                intent.putExtra("app_package", pkg);
                intent.putExtra("app_uid", uid);

            } else {
                //4.4以下并没有提过从app跳转到应用通知设置页面的Action
                openAppDetails(context);
            }
            context.startActivity(intent);

        } catch (Exception e) {
            e.printStackTrace();
            // 出现异常则跳转到应用设置界面：锤子坚果3——OC105 API25
            openSystemSetting(context);
        }
    }

    /**
     * apk应用信息
     * Settings.ACTION_APPLICATION_DETAILS_SETTINGS;  //apk应用信息
     */
    public static void openAppDetails(Context context) {
        //String PKG = "com.android.settings";
        //String CLS = "com.android.settings.applications.InstalledAppDetails";
        Intent intent = new Intent();
        //Context启动Activity最好添加此句，否则可能报错
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            //ComponentName componentName = new ComponentName(PKG, CLS);
            //localIntent.putExtra("package", context.getApplicationInfo().packageName);
            //localIntent.setComponent(componentName);

            intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            //intent.setData(Uri.parse("package:" + pkg));
            intent.setData(Uri.fromParts("package", context.getApplicationInfo().packageName, null));
            context.startActivity(intent);

        } catch (Exception e) {
            //抛出异常就直接打开设置页面
            openSystemSetting(context);
        }
    }

    /**
     * 打开系统设置界面
     * <p>
     * Settings.ACTION_SETTINGS;  //系统设置界面
     */
    public static void openSystemSetting(Context context) {
        try {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_SETTINGS);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            context.startActivity(intent);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void openWIFISetting(Context context) {
        try {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_WIFI_SETTINGS);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

            context.startActivity(intent);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 检查通知栏权限有没有开启
     * 反射
     *
     * @return true-开启通知，false-没有开启通知
     */
    public static boolean isNotificationEnable(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return ((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE)).areNotificationsEnabled();

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
            ApplicationInfo appInfo = context.getApplicationInfo();
            String pkg = context.getApplicationContext().getPackageName();
            int uid = appInfo.uid;

            try {
                Class<?> opsClass = Class.forName(AppOpsManager.class.getName());
                Method checkOpNoThrowMethod = opsClass.getMethod("checkOpNoThrow", Integer.TYPE, Integer.TYPE, String.class);
                Field opPostNotificationValue = opsClass.getDeclaredField("OP_POST_NOTIFICATION");
                int value = (Integer) opPostNotificationValue.get(Integer.class);

                return (Integer) checkOpNoThrowMethod.invoke(appOps, value, uid, pkg) == 0;

            } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
                return true;
            }
        } else {
            return true;
        }
    }

}
